/*
 * Copyright (c) 2013, Klaus Hauschild
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided
 * that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice, this list of conditions and
 *     the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
 *     and the following disclaimer in the documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package de.hauschild.utilsn.core.animation;

import playn.core.GroupLayer;
import playn.core.Image;
import playn.core.ImageLayer;
import playn.core.Layer;
import playn.core.PlayN;

/**
 * @since 0.1.0
 * 
 * @author Klaus Hauschild
 */
public class AnimationImpl implements Animation {

  private AnimationState animationState = AnimationState.PAUSED;
  private int currentTime = 0;
  private int currentFrame = 0;
  private final GroupLayer layer;
  private final ImageLayer[] frames;
  private final int millisPerFrame;
  private final boolean looping;

  AnimationImpl(final Image[] images, final int millisPerFrame) {
    this(images, millisPerFrame, false);
  }

  AnimationImpl(final Image[] images, final int millisPerFrame, final boolean looping) {
    layer = PlayN.graphics().createGroupLayer();
    frames = new ImageLayer[images.length];
    for (int i = 0; i < images.length; i++) {
      frames[i] = PlayN.graphics().createImageLayer(images[i]);
    }
    layer.add(frames[0]);
    this.millisPerFrame = millisPerFrame;
    this.looping = looping;
  }

  @Override
  public Layer getLayer() {
    return layer;
  }

  @Override
  public AnimationState getState() {
    return animationState;
  }

  @Override
  public void paint(final float alpha) {
  }

  @Override
  public void pause() {
    animationState = AnimationState.PAUSED;
  }

  @Override
  public void play() {
    animationState = AnimationState.PLAYING;
  }

  @Override
  public void stop() {
    animationState = AnimationState.PAUSED;
    currentTime = 0;
  }

  @Override
  public void update(final int delta) {
    if (animationState == AnimationState.PLAYING) {
      currentTime += delta;
      if (currentTime >= duration()) {
        if (looping) {
          currentTime = duration() - currentTime;
          if (currentTime < 0) {
            currentTime = 0;
          }
        } else {
          pause();
        }
      }
    }
    final int frame = currentTime / millisPerFrame;
    if (currentFrame != frame) {
      layer.remove(frames[currentFrame]);
      layer.add(frames[frame]);
      currentFrame = frame;
    }
  }

  private int duration() {
    return frames.length * millisPerFrame;
  }

}
